/*
 * Copyright (C), 2020, 安徽艾伦家居饰品有限公司
 * FileName: RefreshApiService
 * Author:   Allen
 * Date:     2020/8/19
 * Description: 动态刷入API接口类
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.haoyu.auth.core.service.impl;

import com.haoyu.auth.client.constant.AuthServiceConstant;
import com.haoyu.auth.client.constant.AuthEnumConstant;
import com.haoyu.common.exception.ServiceException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.util.List;

/**
 * 通过restTemplate来调用swagger接口数据动态刷入API接口数据
 * @author Allen
 * @date 2020/8/19
 */
@Slf4j
@Component
public class RefreshApiServiceImpl {

    /**
     * 初始化RestTemplate
     * @return RestTemplate
     */
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    /**
     * 引入DiscoveryClient
     */
    @Autowired
    private DiscoveryClient discoveryClient;

    /**
     *  注入RestTemplate
     */
    @Autowired
    private RestTemplate restTemplate;

    /**
     * API接口服务service服务
     */
    @Autowired
    private ApiServiceImpl apiService;

    /**
     * 刷入api列表数据
     * List<String> services = discoveryClient.getServices();
     * services.forEach(service -> listServiceInstance.addAll(discoveryClient.getInstances(service)));
     * 去掉上述两行，更改成指定服务ID来刷新，而不是全部刷新，这样如果服务过多，易造成时间过长。
     * @param serviceId 服务ID
     * @return 返回刷入是否成功
     */
    @Async
    public Boolean refreshListApi(String serviceId) {
        List<ServiceInstance> listServiceInstance = discoveryClient.getInstances(serviceId);
        for (ServiceInstance serviceInstance : listServiceInstance) {
            String hostIp = serviceInstance.getHost();
            String serviceName = serviceInstance.getServiceId();
            int servicePort = serviceInstance.getPort();
            log.debug("[服务列表信息] => host-->" + hostIp + ";serviceName-->" + serviceName + ";port-->" + servicePort);
            //此处需获得各个服务的contextPath，否则无法调用/v2/api-docs
            String contextPath;
            switch (serviceName) {
                case AuthServiceConstant.MIDDLE_SERVER:
                    contextPath = AuthServiceConstant.MIDDLE_CONTEXT_PATH;
                    break;
                case AuthServiceConstant.AUTH_SERVER:
                    contextPath = AuthServiceConstant.AUTH_CONTEXT_PATH;
                    break;
                default:
                    //TODO 此处需要动态获得各应用的contextPath
                    contextPath = "/";
                    break;
            }
            String swaggerJson;
            try {
                String url = "http://" + serviceName + ":" + servicePort + contextPath + "/v2/api-docs";
                swaggerJson = restTemplate.getForEntity(url, String.class).getBody();
                log.debug("[调用swaggerApi地址为] =>" + url);
                apiService.refreshApi(swaggerJson, serviceInstance.getServiceId().toLowerCase());
                return true;
            } catch (RestClientException error) {
                log.error("[未检测到swagger数据或contextPath异常，刷入api列表数据错误]：" + error);
                throw new ServiceException(AuthEnumConstant.REFRESH_API_ERROR);
            }
        }
        return false;
    }

}
